#!/usr/bin/env python
import flowd
import string
import getopt
import sys
import os
import ipcalc

action_types = [
	"src_addr",
	"dst_addr",
	"src_prefix",
	"dst_prefix",
	"src_port",
	"dst_port",
	"exporter",
	"nexthop",
	"src_as",
	"dst_as",
	"protocol",
	"tos",
	"input_interface",
	"output_interface"
]

class filter_action:
	def __init__(self):
		self.field = ""
		self.values = []
	def set_field(self, name):
		self.field = name
	def add_value(self, value):
		self.values.append(value)
	def set_value(self, value):
		self.values = value

		
def whatflowfield(field, flow):
	if field == "src_addr" or field == "src_prefix":
		return flow.src_addr
	elif field == "dst_addr" or field == "dst_prefix":
		return flow.dst_addr
	elif field == "src_port":
		return flow.src_port
	elif field == "dst_port":
		return flow.dst_port
	elif field == "src_as":
		return flow.src_as
	elif field == "dst_as":
		return flow.dst_as
	elif field == "protocol":
		return flow.protocol
	elif field == "tos":
		return flow.tos
	elif field == "exporter":
		return flow.agent_addr
	elif field == "nexthop":
		return flow.gateway_addr
	elif field == "input_interface":
		return flow.if_ndx_in
	elif field == "output_interface":
		return flow.if_ndx_out
	return None
	

def usage():
	print >> sys.stderr, "filter.py (flowd.py version %s)" % \
	    flowd.__version__
	print >> sys.stderr, "Usage: filter.py [options] [flowd-store]";
	print >> sys.stderr, "Options:";
	print >> sys.stderr, "      -h       Display this help";
	print >> sys.stderr, "      -f       Path to filterfile";
	print >> sys.stderr, "      -F       Filter name";
	print >> sys.stderr, "      -o       output file";
	#print >> sys.stderr, "Example of tagfile:\n";
	#print >> sys.stderr, "tag-action tag\n type src_addr\n match 192.168.231.1\n match 192.168.231.2\ntag-action tag2\n type src_port\n match 138\ntag-definition 1\n action tag\n action tag2\ntag-definition 2\n action tag2\n";
	#print >> sys.stderr, "  tag-action types: %s"% ', '.join(action_types);
	sys.exit(1);
	
def main():

	try:
		opts, args = getopt.getopt(sys.argv[1:], 'f:F:o:h')
	except getopt.GetoptError:
		print >> sys.stderr, "Invalid commandline arguments"
		usage()

	filepath = None
	filter = None
	output_file = None
	for o, a in opts:
		if o in ('-h', '--help'):
			usage()
			sys.exit(0)
		if o in ('-f'):
			filepath = a
		if o in ('-F'):
			filter = a
		if o in ('-o'):
			output_file = a

	if filepath is None:
		print >> sys.stderr, "No tagfile specified"
		usage()
			
	if filter is None:
		print >> sys.stderr, "No tag specified"
		usage()		
			
	if len(args) == 0:
		print >> sys.stderr, "No logfile specified"
		usage()

	#parsing tagfile
	tagfile = open(filepath, "r")
	tagacthash = {}
	line = tagfile.readline()
	while line.strip().startswith("filter-action"):
		tagactname = line.strip().split(" ")[1]
		line = tagfile.readline()
		tagactrules = []
		while line.strip().startswith("type"):
			tagacttype = line.strip().split(" ")[1]
			tagact = filter_action()
			tagact.set_field(tagacttype)
			line = tagfile.readline()
			while line.strip().startswith("match"):
				tagactval = line.strip().split(" ")[1]
				if tagacttype=="src_prefix" or tagacttype=="dst_prefix":
					tagact.set_value(ipcalc.Network(tagactval))
				else:
					tagact.add_value(tagactval)
				line = tagfile.readline()
			tagactrules.append(tagact)
		tagacthash[tagactname] = tagactrules
	while line.strip().startswith("filter-definition"):
		tag = line.strip().split(" ")[1]
		line = tagfile.readline()
		tagactnames = []
		while line.strip().startswith("action"):
			tagactnames.append(line.strip().split(" ")[1])
			line = tagfile.readline()
		if tag == filter:
			break
	for tname in tagactnames:
		for rule in tagacthash[tname]:
			print rule.field, rule.values
	#print int(tagnum,16)
	
	#writing tags	
	file = open("filt", "w")
	for ffile in args:
		flogr = flowd.FlowLog(ffile, "rb")
		if output_file is not None:
			flogw = flowd.FlowLog(output_file, "wb")
		for flow in flogr:
			trueact = 0
			term = 1
			for tname in tagactnames:
				for rule in tagacthash[tname]:
					if str(whatflowfield(rule.field, flow)) in rule.values:
						trueact = 1
						break
					else: 
						trueact = 0
				term = term * trueact
			
			if term == 1:		
				print flow.format(mask = flowd.DISPLAY_BRIEF, utc = 1)
				file.write(flow.format(mask = flowd.DISPLAY_BRIEF, utc = 1))
				if output_file is not None:
					flogw.write_flow(flow)
	file.close()
if __name__ == '__main__': main()